﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Batty
{
    public class Rats
    {



        public class Rat
        {
            public Pondhawk game;
            public Model model;
            public int frontleft;          // Index to the wing 1 bone
            public int frontright;          // Index to the wing 2 bone
            public int backleft;          // Index to the wing 1 bone
            public int backright;          // Index to the wing 2 bone
            public float legangle1 = 0f; // Current wing deployment angle
            public float legangle2 = -.8f; // Current wing deployment angle
            public int legState = 1;
            public float confusedTime = 0;
            public bool confused = false;
            public float speed = 2;
            public Vector3 position = Vector3.Zero;
            public float azimuth = 0;
            public bool remove = false;
            public float tailangle=.8f;
            public int tail;
            public int tail2, tail3,tail4;
            public int tailState=1;


            public void DrawModel(GraphicsDeviceManager graphics, Model model, Matrix world, Pondhawk game)
            {
                Matrix[] transforms = new Matrix[model.Bones.Count];
                model.CopyAbsoluteBoneTransformsTo(transforms);
                
                transforms[frontleft] = Matrix.CreateRotationX(legangle1) * transforms[frontleft];
                transforms[frontright] = Matrix.CreateRotationX(-legangle1) * transforms[frontright];
                transforms[backleft] = Matrix.CreateRotationX(-legangle1) * transforms[backleft];
                transforms[backright] = Matrix.CreateRotationX(legangle1) * transforms[backright];
                transforms[tail4] = Matrix.CreateRotationZ(tailangle) * transforms[tail4];
      
  
                


                foreach (ModelMesh mesh in model.Meshes)
                {
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        effect.EnableDefaultLighting();
                        effect.World = transforms[mesh.ParentBone.Index] * world;
                        effect.View = game.Camera.View;
                        effect.Projection = game.Camera.Projection;
                    }
                    mesh.Draw();
                }
            }
        }









        private Pondhawk game;
        public LinkedList<Rat> rats = new LinkedList<Rat>();
        public LinkedList<Rat> RatsList { get { return rats; } }
        public LinkedList<Rat> ratsCopy = new LinkedList<Rat>();
        public LinkedList<Rat> RatsListCopy { get { return ratsCopy; } }
        private Random random = new Random();




        public Rats(Pondhawk game)
        {
            this.game = game;
        }
        public void LoadContent(ContentManager content)
        {

            while (rats.Count < 50)
            {
                Rat rat = new Rat();
                rat.model = content.Load<Model>("Rat-rigid");
                rat.frontleft = rat.model.Bones.IndexOf(rat.model.Bones["LeftFrontLeg"]);
                rat.frontright = rat.model.Bones.IndexOf(rat.model.Bones["RightFrontLeg"]);
                rat.backleft = rat.model.Bones.IndexOf(rat.model.Bones["LeftBackLeg"]);
                rat.backright = rat.model.Bones.IndexOf(rat.model.Bones["RightBackLeg"]);
                rat.tail = rat.model.Bones.IndexOf(rat.model.Bones["Tail1"]);
                rat.tail2 = rat.model.Bones.IndexOf(rat.model.Bones["Tail2"]);
                rat.tail3 = rat.model.Bones.IndexOf(rat.model.Bones["Tail3"]);
                rat.tail4 = rat.model.Bones.IndexOf(rat.model.Bones["Tail4"]);
                rat.position = RandomXZVector(-200, 200);
                rat.azimuth = (float)Math.Atan2(-(float)rat.position.X, -(float)rat.position.Z);
                rats.AddLast(rat);
            }

        }

        public void Update(GameTime gameTime)
        {


            foreach (Rat rat in RatsList)
            {





                float legMoveTime = .7f;
                if (rat.legState == 0)
                    rat.legangle1 += (float)(0.30 * gameTime.ElapsedGameTime.TotalSeconds / legMoveTime);
                else
                    rat.legangle1 -= (float)(0.30 * gameTime.ElapsedGameTime.TotalSeconds / legMoveTime);
                if (rat.legangle1 >= 0.30f)
                {
                    rat.legangle1 = 0.30f;
                    rat.legState = 1;
                }
                if (rat.legangle1 <= -0.30f)
                {
                    rat.legangle1 = -0.30f;
                    rat.legState = 0;
                }
                if(rat.tailState==0)
                    rat.tailangle += (float)(0.30 * gameTime.ElapsedGameTime.TotalSeconds / legMoveTime);
                else
                    rat.tailangle -= (float)(0.30 * gameTime.ElapsedGameTime.TotalSeconds / legMoveTime);
                if (rat.tailangle >= 0.50f)
                {
                    rat.tailangle = 0.50f;
                    rat.tailState = 1;
                }
                if (rat.tailangle <= -0.50f)
                {
                    rat.tailangle = -0.50f;
                    rat.tailState = 0;
                }
                Matrix transform = Matrix.CreateRotationY(rat.azimuth);
                Vector3 directedThrust = Vector3.TransformNormal(new Vector3(0, 0, 1), transform);
                rat.position += directedThrust * rat.speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
                // System.Diagnostics.Trace.WriteLine(rat.legangle1.ToString());
            }

            //RatsListCopy=RatsList.ToArray();
        }

        public void Draw(GraphicsDeviceManager graphics, GameTime gameTime, Pondhawk game)
        {
            foreach (Rat rat in RatsList)
            {
             
                Matrix transform = Matrix.CreateRotationY(rat.azimuth) * Matrix.CreateTranslation(rat.position);

                rat.DrawModel(graphics, rat.model, transform, game);

            }

        }


        public void addRat(ContentManager content)
        {
            Rat rat = new Rat();
            rat.model = content.Load<Model>("Rat-rigid");
            rat.frontleft = rat.model.Bones.IndexOf(rat.model.Bones["LeftFrontLeg"]);
            rat.frontright = rat.model.Bones.IndexOf(rat.model.Bones["RightFrontLeg"]);
            rat.backleft = rat.model.Bones.IndexOf(rat.model.Bones["LeftBackLeg"]);
            rat.backright = rat.model.Bones.IndexOf(rat.model.Bones["RightBackLeg"]);
            rat.position = RandomXZVector(-200, 200);
            rat.azimuth = (float)Math.Atan2(-(float)rat.position.X, -(float)rat.position.Z);
            rats.AddLast(rat);
            //after a given amount of time add a rat
        }

        private Vector3 RandomXZVector(float min, float max)
        {
            Vector3 pos =new Vector3((float)(min + (random.NextDouble() * (max - min))+50f),
                (float)1,
                (float)(min + (random.NextDouble() * (max - min)))+50f);
            if (pos.X>=0)
                pos.X+=50f;
            else
                pos.X-=50f;
            if (pos.Z>=0)
                pos.Z+=50f;
            else
                pos.Z-=50f;
            return pos;
        }


        public void testEchoForCollision(Vector3 position)
        {
          

            for (LinkedListNode<Rat> ratNode = RatsList.First; ratNode != null; )
            {
                LinkedListNode<Rat> nextNode = ratNode.Next;
                Rat rattest = ratNode.Value;
                //System.Diagnostics.Trace.WriteLine("Checking Rats2");
                // Obtain a bounding sphere for the asteroid.  I can get away
                // with this here because I know the model has exactly one mesh
                // and exactly one bone.
                BoundingSphere bs = rattest.model.Meshes[0].BoundingSphere;
                bs = bs.Transform(rattest.model.Bones[0].Transform);

                // Move this to world coordinates.  Note how easy it is to 
                // transform a bounding sphere
                bs.Radius += 4;
                bs.Center += rattest.position;


                if ((position - bs.Center).LengthSquared() < bs.Radius * bs.Radius)
                {
                     System.Diagnostics.Trace.WriteLine("HIT");
                    // float angle = (float)Math.Atan2((float)rattest.position.X, (float)rattest.position.Z);
                    float angle = .1f;
                    rattest.azimuth += angle;
                    rattest.confused = true;
                    //rattest.position=new Vector3((float)(rattest.position.X*Math.Cos(angle)+rattest.position.Z*Math.Sin(angle)),rattest.position.Y,(float)(rattest.position.X*Math.Sin(-angle)+rattest.position.Z*Math.Cos(angle)));
                }
               

                    
               
                ratNode = nextNode;
            }
        }

        
        public bool testRatsForCollision(Rat rat)
        {
            //for rat in rats test with rats after it
            //remove both rats, make a squeal sound

            //my bounding spheres are wrong!!!!!!!!!!!!!!!

            BoundingSphere ratsphere = rat.model.Meshes[0].BoundingSphere;
            ratsphere = ratsphere.Transform(rat.model.Bones[0].Transform);
            ratsphere.Center += rat.position;
            //  System.Diagnostics.Trace.WriteLine("Checking Rats");
            for (LinkedListNode<Rat> ratNode = RatsList.First; ratNode != null; )
            {
                LinkedListNode<Rat> nextNode = ratNode.Next;
                Rat rattest = ratNode.Value;
                //System.Diagnostics.Trace.WriteLine("Checking Rats2");
                // Obtain a bounding sphere for the asteroid.  I can get away
                // with this here because I know the model has exactly one mesh
                // and exactly one bone.
                BoundingSphere bs = rattest.model.Meshes[0].BoundingSphere;
                bs = bs.Transform(rattest.model.Bones[0].Transform);

                // Move this to world coordinates.  Note how easy it is to 
                // transform a bounding sphere
                bs.Radius += 4;
                bs.Center += rattest.position;

                if (ratsphere.Intersects(bs) && ratsphere.Center != bs.Center)
                {
                    //System.Diagnostics.Trace.WriteLine("Removing Rats");
                    ratNode.Value.remove = true;
                    // rats.Remove(ratNode);
                }
                else
                {
                    //  rats.Remove(ratNode);
                    // System.Diagnostics.Trace.WriteLine("NOT Removing Rats");
                    // ratsCopy.AddLast(rat);

                }

                ratNode = nextNode;
            }

            if (rat.remove == false)
                ratsCopy.AddLast(rat);

            return false;
        }

        public void checkConfusionState(float time)
        {
            for (LinkedListNode<Rat> ratNode = RatsList.First; ratNode != null; )
            {
                LinkedListNode<Rat> nextNode = ratNode.Next;
                Rat rattest = ratNode.Value;
                rattest.confusedTime += time;
                if (rattest.confused == true)
                {


                    if (rattest.confusedTime >= 8)
                    {
                        System.Diagnostics.Trace.WriteLine("Continue the Attack!");
                        rattest.azimuth = (float)Math.Atan2(-(float)rattest.position.X, -(float)rattest.position.Z);
                        rattest.confused = false;
                        rattest.confusedTime = 0f;
                    }
                }




                ratNode = nextNode;
            }
        }

        public bool checkLost(BoundingSphere lego)
        {

            //  System.Diagnostics.Trace.WriteLine("Checking Rats");
            for (LinkedListNode<Rat> ratNode = RatsList.First; ratNode != null; )
            {
                LinkedListNode<Rat> nextNode = ratNode.Next;
                Rat rattest = ratNode.Value;

                BoundingSphere bs = rattest.model.Meshes[0].BoundingSphere;
                bs = bs.Transform(rattest.model.Bones[0].Transform);

                bs.Radius += 6;
                bs.Center += rattest.position;

                if (lego.Intersects(bs))
                {
                   return true;
                }


                ratNode = nextNode;
            }

            return false;
        
        }

    }
}
